<script setup lang="ts">
import { PlayStatus, useAudioPlayerStore } from '@/stores'
import { nextTick, onBeforeMount, onMounted, ref, watch } from 'vue'
import { parse } from '@/utils/qrc'
import { parse as parseLrc } from '@/utils/lrc'
import { each } from 'lodash'

const LyricReady = ref<boolean>(false)

const LyricText = ref("<p>暂无歌词</p>")

const boxRef = ref(null)

const lyricBodyRef = ref<HTMLDivElement| null>(null)
const lyricRef = ref<HTMLDivElement| null>(null)

const lyricContentMargin = 26

type LyricType = 'qrc' | 'lrc'

const lyricType = ref<LyricType>('qrc')

let animationFrameId:number = 0

const setBoxWidth = ()=>{
  if (boxRef.value !== null)
  {
    //boxRef.value.style.width = '450px'
  }
}

const displayLyricDefault = () =>{
  if(lyricRef.value && lyricBodyRef.value)
  {
    const offset = lyricBodyRef.value.offsetHeight / 2
    console.log("sss",offset,lyricBodyRef.value.offsetHeight)
    lyricRef.value.style.top = `${offset}px`
  }
}

onMounted(()=>{
  displayLyricDefault()
  if(audioPlayer && audioPlayer.status == PlayStatus.playing)
  {
    startDisplayLyric()
  }
})

const displayLyricQrc = (time:number)=>{
  if(lyricRef.value && lyricBodyRef.value)
  {
    const offset = lyricBodyRef.value.offsetHeight / 2
    const LyricTime = time * 1000
    const lyrics = document.querySelectorAll('.lyric-body .lyric-content p')

    for(let i = 0; i< lyrics.length; i++)
    {
      //const LineHeight = lyrics[i].offsetHeight + lyricContentMargin
      const LineHeight = 23 + lyricContentMargin
      if(lyrics[i].dataset && lyrics[i].dataset.start)
      {
        const pTime = parseInt(lyrics[i].dataset.start)
        const pDTime = parseInt(lyrics[i].dataset.duration)
        const endTime = pTime + pDTime
        const next = ((i+1) < lyrics.length) ? lyrics[i+1] : null
        const pre = ((i-1) >= 0) ? lyrics[i-1] : null
        if((LyricTime >= pTime && LyricTime <= endTime) || (LyricTime > endTime && next === null) || next && LyricTime > endTime && LyricTime < next.dataset.start )
        {
          const top = offset - (LineHeight * (i +1))
          lyricRef.value.style.top = `${top}px`
          lyrics[i].className = 'playing'
          each(lyrics[i].children,(span)=>{
            const wordTime = LyricTime - parseInt(lyrics[i].dataset.start)
            //console.log(`${LyricTime}-${lyrics[i].dataset.start}=${wordTime}`)
            const sTime = parseInt(span.dataset.start)
            const sDTime = parseInt(span.dataset.duration)
            const sEndTime = sTime + sDTime
            const pStart = wordTime - sEndTime
            const animation = 'lyricWordDisplay2 ' + `${sDTime/1000}s ` + 'linear 1 both'
            const animationOver = 'lyricWordDisplay2 ' + `0s ` + 'linear 1 both'
            if(wordTime >= sEndTime)
            {
              if(span.className !== 'played')
              {
                span.className = 'played'
                span.style.animation = animationOver
              }
              else {
                span.className = 'played'
              }

            }
            else if(wordTime >= sTime)
            {
              // if(span.className !== 'play' && span.style.animation !== animation)
              // {
              //   //有可能是通过setTime切换到这里，动画剩余时间就不是全部的 duration
              //   console.log(span.style.animation)
              // }
              span.className = 'play'
              span.style.animation = animation

            }
            else{
              span.className = 'no'
              span.style.animation = 'none'
            }

          })
          if(next)
          {
            each(next.children,(span)=>{
              span.className = 'no'
              span.style.animation = 'none'
            })
          }

          // if(pre)
          // {
          //   each(pre.children,(span)=>{
          //     span.className = 'no'
          //     span.style.animation = 'none'
          //   })
          // }

        }
        else {
          lyrics[i].className = ''
        }
      }

    }
  }
}

const displayLyricLrc = (time:number)=>{
  if(lyricRef.value && lyricBodyRef.value)
  {
    const offset = lyricBodyRef.value.offsetHeight / 2
    const LyricTime = time * 1000
    const lyrics = document.querySelectorAll('.lyric-body .lyric-content p')

    for(let i = 0; i< lyrics.length; i++)
    {
      //const LineHeight = lyrics[i].offsetHeight + lyricContentMargin
      const LineHeight = 23 + lyricContentMargin
      if(lyrics[i].dataset && lyrics[i].dataset.start)
      {
        const pTime = parseInt(lyrics[i].dataset.start)
        const next = ((i+1) < lyrics.length) ? lyrics[i+1] : null
        const endTime = next ? parseInt(next.dataset.start) : 10000000000

        if((LyricTime >= pTime && LyricTime <= endTime))
        {
          const top = offset - (LineHeight * (i + 1))
          lyricRef.value.style.top = `${top}px`
          lyrics[i].className = 'playing'

        }
        else {
          lyrics[i].className = ''
        }
      }

    }
  }
}

type lyric = {
  al:string,
  ar:string,
  by:string,
  content: Array<lyricContentQrc | lyricContentLrc>,
  offset: number,
  ti: string,
  type: string
}

type lyricSubContentQrc = {start:number,duration:number,content:string}
type lyricSubContentLrc = {start:number,content:string}
type lyricContentQrc = {start:number,duration:number,content:Array<lyricSubContentQrc>}
type lyricContentLrc = {start:number,content:Array<lyricSubContentLrc>}

const LyricObeject = ref<lyric | null>(null)

const objToHtmlStringQrc = (obj: lyricContentQrc[]) => {
  let str:string = ''
  each(obj,(content)=>{
    let sub:string = ''
    each(content.content,(text)=>{
      sub+= '<span data-duration="'+ text.duration+'" data-start="'+ text.start+'" data-content="'+ text.content +'">' +text.content + '</span>'
      // sub+= '<span style="animation-delay: '+ `${text.duration}ms` +';" data-duration="'+ text.duration+'" data-start="'+ text.start+'" data-content="'+ text.content +'">' +text.content + '</span>'
    })
    str += '<p data-duration="' + content.duration +'" data-start="'+ content.start+'">' + sub+ '</p>'
  })
  //console.log(str)
  LyricText.value = str
}

const objToHtmlStringLrc = (obj: lyricContentLrc[]) => {
  let str:string = ''
  each(obj,(item)=>{
    let sub:string = ''
    str += '<p data-start="'+ item.start+'">' + item.content+ '</p>'
  })
  //console.log(str)
  LyricText.value = str
}

onBeforeMount(()=>{
  if(audioPlayer.playingSong)
  {
    getLyric(audioPlayer.playingSong)
  }
})

const audioPlayer = useAudioPlayerStore()

watch(()=>audioPlayer.playingSong,async (newValue)=>{
  if(newValue)
  {
    getLyric(newValue)
  }
})

watch(()=>audioPlayer.status,async (newValue)=>{
  if(newValue === PlayStatus.playing)
  {
    startDisplayLyric()
  }
  else if(newValue === PlayStatus.pause)
  {
    if(lyricType.value && lyricType.value === "qrc")
    {
      pauseLyricAnimation()
    }

    cancelAnimationFrame(animationFrameId);

  }else
  {
    cancelAnimationFrame(animationFrameId);
  }

})

const pauseLyricAnimation = ()=>{
  const lyricPlaying = document.querySelector('.lyric-body .lyric-content .playing')
  if(lyricPlaying)
  {
    lyricPlaying.className = 'pause'
  }
}


const startDisplayLyric = ()=>{
  if(audioPlayer.musicPlayer && LyricReady)
  {
    var dataArray = new Uint8Array(audioPlayer.analyser.frequencyBinCount);
    audioPlayer.analyser.getByteTimeDomainData(dataArray);
    const currentTime = audioPlayer.musicPlayer.currentTime
    switch (lyricType.value)
    {
      case 'qrc':
        displayLyricQrc(currentTime)
        break;
      case 'lrc':
        displayLyricLrc(currentTime)
        break;
    }

  }
  animationFrameId = requestAnimationFrame(startDisplayLyric);
}


const getLyric = (newValue:song_info)=>{
  const resQrc =  handleLyricQrc(newValue)
  if(resQrc){
    try{
      LyricObeject.value = resQrc as lyric
      LyricReady.value = true
      objToHtmlStringQrc(LyricObeject.value.content)
      lyricType.value = 'qrc'
    }
    catch(e) {
      console.log("格式错误")
      errLyric()
    }
  }
  else {
    const resLrc = handleLyricLrc(newValue)
    if(resLrc) {
      LyricObeject.value = resLrc as lyric
      LyricReady.value = true
      objToHtmlStringLrc(LyricObeject.value.content)
      lyricType.value = 'lrc'
      console.log(resLrc)
      //errLyric()
    }
    else{
      console.log("解析失败")
      errLyric()
    }

  }
  nextTick(()=>{
    setBoxWidth()
  })

}

const errLyric = ()=>{
  LyricReady.value = false
  LyricObeject.value = null
  LyricText.value = "<p>歌词还在来的路上 (╬◣д◢) </p>"
  displayLyricDefault()

}

const handleLyricQrc = (value: song_info | null): Object | null =>{
  if(value && value.lyrics)
  {
    try{
      return parse(value.lyrics)
    }
    catch (e) {
      return null
    }
  }
  return null
}

const handleLyricLrc = (value: song_info | null): Object | null =>{
  if(value && value.lyrics)
  {
    try{
      return parseLrc(value.lyrics)
    }
    catch (e) {
      return null
    }
  }
  return null
}


</script>

<template>
  <div class="right-box" ref="boxRef">
    <div class="lyric-header">
      <h2>{{ audioPlayer.playingSong ? audioPlayer.playingSong.title : 'QQ音乐'}}</h2>
      <p>歌手: &nbsp;&nbsp;{{ audioPlayer.playingSong ? audioPlayer.playingSong.artist_name : ''  }}</p>
      <p>专辑: &nbsp;&nbsp;{{ audioPlayer.playingSong ? audioPlayer.playingSong.album_name : '' }}</p>
    </div>
    <div class="lyric-body" ref="lyricBodyRef">
      <div class="lyric-content" :class="lyricType" ref="lyricRef" v-html="LyricText">
      </div>
    </div>
  </div>
</template>

<style scoped lang="scss">
.right-box{
  text-align: center;
  height: 50vh;
  overflow: hidden;
  min-width: 450px;
  width: fit-content;

  .lyric-header{
    color: #9a8c89;
    font-size: 13px;
    margin-bottom: 40px;
    max-width: 45vw;
    h2{
      color: #fffefb;
      font-size: 20px;
      margin-bottom: 25px;
    }
  }

  .lyric-body{
    overflow: hidden;
    height: 35vh;
    //color: #f8f5f6;
    font-size: 16px;
    position: relative;
    z-index: 1000;

    .lyric-content{
      position: absolute;
      width: 100%;
      top: 50%;
      left: 50%;
      transform: translateX(-50%);
      transition: all .5s ease-in-out;
      z-index: 1002;
      color: #fff;
    }
  }

  :global(.lyric-body p){
    height: 23px;
    margin: 26px 0;
    transition: all 0.3s;
  }

  :global(.lyric-body p span){
    //color: #f8f5f6;
    color: #fff;
    font-weight: 500;
  }

}
</style>